1 00:00:00,400 --> 00:00:06,550 In this lecture, we're going to learn how to script a sliding UI bar to allow our players to independently 2 00:00:06,550 --> 00:00:11,770 control the transparency of other players in the game, as shown here. 3 00:00:12,880 --> 00:00:18,670 So each player in the game is able to control whether or not they'd like to see other players characters 4 00:00:18,670 --> 00:00:20,800 when they are going through the Abbey. 5 00:00:21,040 --> 00:00:23,680 So let's go ahead and get started. 6 00:00:24,970 --> 00:00:31,000 We're going to create a new script or a module script inside of starter player scripts and our handler 7 00:00:31,000 --> 00:00:31,450 section. 8 00:00:31,450 --> 00:00:32,830 So we'll call this. 9 00:00:33,570 --> 00:00:41,220 Our setting guy handler, and we're going to use that same template that we've used before. 10 00:00:41,610 --> 00:00:43,140 We'll paste that in here. 11 00:00:43,140 --> 00:00:47,160 I'm going to rename this to our setting guy handler. 12 00:00:47,190 --> 00:00:51,480 Again you use control shift and R to rename a variable. 13 00:00:52,170 --> 00:00:58,200 And inside of here we want to create some functions for updating transparency for players in our game. 14 00:00:58,500 --> 00:01:04,320 For example, we want to have a function to update the transparency for a particular character. 15 00:01:04,320 --> 00:01:09,240 So we would pass a character as well as the transparency to set for this character. 16 00:01:09,270 --> 00:01:16,050 We would also like to have a function to update all of the transparency for players in our game. 17 00:01:16,050 --> 00:01:19,140 So we could call this function update. 18 00:01:19,840 --> 00:01:24,730 Transparency for all players. 19 00:01:24,730 --> 00:01:28,180 And again, we would pass a transparency value here. 20 00:01:28,180 --> 00:01:32,440 And this would go and loop through all of the players in our game, see if they have a character and 21 00:01:32,440 --> 00:01:35,350 then use the update transparency for function on them. 22 00:01:35,770 --> 00:01:40,240 And then we also want to make sure we listen to whenever a player's character is added to the game. 23 00:01:40,240 --> 00:01:45,940 So if another player's, uh, character dies and then they respawn with a new character, we want to 24 00:01:45,940 --> 00:01:51,400 make sure we update the transparency of all of the descendants in that character, equal to whatever 25 00:01:51,400 --> 00:01:55,750 the current transparency our player has for their guy. 26 00:01:55,750 --> 00:02:02,110 So we'll create a function to listen for when a character is added and that will get passed a character. 27 00:02:03,600 --> 00:02:10,320 And then we also need a function to go ahead and calculate the current transparency based on the position 28 00:02:10,320 --> 00:02:13,470 of the slider across this bar here. 29 00:02:13,470 --> 00:02:19,320 So we'll call this function calculate and update transparency. 30 00:02:20,390 --> 00:02:25,160 Now, to make this transparency slider work, we're going to need the run service. 31 00:02:26,080 --> 00:02:29,980 We're also going to need the players service as well. 32 00:02:31,320 --> 00:02:34,920 And then we're also going to need the user input service. 33 00:02:34,920 --> 00:02:41,370 That way we can go ahead and listen for when the player releases their mouse button or stops input, 34 00:02:41,370 --> 00:02:49,680 which notifies us to, uh, basically have this slider stop following the player's, uh, mouse. 35 00:02:50,220 --> 00:02:55,620 So what we can go ahead and do is create a variable for our player. 36 00:02:55,620 --> 00:02:59,100 We'll call it local player and that's equal to players dot local player. 37 00:02:59,280 --> 00:03:01,680 We'll get the guy that we need to affect. 38 00:03:01,680 --> 00:03:04,590 So inside of starter GUI we have a setting GUI. 39 00:03:04,740 --> 00:03:06,810 So that's going to be equal to our local player. 40 00:03:06,900 --> 00:03:11,310 Get their player GUI folder and we're going to wait for that guy to replicate. 41 00:03:12,000 --> 00:03:16,980 And then we're also going to go ahead and grab that button that they can click to drag around the slider. 42 00:03:16,980 --> 00:03:19,200 So we'll call that the transparency button. 43 00:03:19,200 --> 00:03:23,790 And that's in the GUI dot main frame dot transparency slider. 44 00:03:23,790 --> 00:03:26,790 And there's a button in there called text button. 45 00:03:28,290 --> 00:03:32,490 Then we can have a buoyant to tell whether or not we're currently pressing down on that button. 46 00:03:32,490 --> 00:03:34,110 So we'll call it currently. 47 00:03:34,960 --> 00:03:38,560 Pressing button and we'll set that equal to false by default. 48 00:03:38,590 --> 00:03:43,540 We'll also have a variable to keep track of the current transparency they have set, which is going 49 00:03:43,540 --> 00:03:45,220 to be zero by default. 50 00:03:45,820 --> 00:03:51,940 And then since we're going to be using the run service to constantly update the position of that slider, 51 00:03:52,480 --> 00:03:58,030 um, we're going to be using some functions in there like Udim two and math dot clamp. 52 00:03:58,030 --> 00:04:04,060 And it's actually faster if we store those functions in local variables on our machine instead of having 53 00:04:04,060 --> 00:04:07,750 to index, uh, globals for those functions. 54 00:04:07,750 --> 00:04:09,280 So we'll create two variables. 55 00:04:09,280 --> 00:04:14,530 I'll call one of them new Udim two and the other one we're just going to call clamp. 56 00:04:14,530 --> 00:04:20,620 And that's going to be equal to Udim two dot new as well as math dot clamp. 57 00:04:20,620 --> 00:04:26,140 So we're basically copying these functions and storing them in local variables which makes them faster 58 00:04:26,140 --> 00:04:27,880 to reference under the hood. 59 00:04:28,540 --> 00:04:34,270 Now what we can go ahead and do in our initialize function is we can listen for when a player is added 60 00:04:34,270 --> 00:04:35,530 to the game. 61 00:04:35,980 --> 00:04:37,060 And we'll get that player. 62 00:04:37,060 --> 00:04:40,510 And we want to listen for when that player has a character added. 63 00:04:40,510 --> 00:04:45,100 And we connect the on character added function to that event. 64 00:04:45,100 --> 00:04:48,550 And then we also want to loop through all of the existing players in our game. 65 00:04:48,550 --> 00:04:55,990 So for every player and player's get, players we want to do is we want to make sure that this player 66 00:04:55,990 --> 00:04:58,300 is not equal to our local player. 67 00:04:58,820 --> 00:05:02,060 So if it is, we'll just continue looping to the next player. 68 00:05:02,270 --> 00:05:08,960 Otherwise, we'll connect to the character added event with our on character added function. 69 00:05:10,550 --> 00:05:16,130 And then inside of the start function is where we're going to be listening for all the input on our 70 00:05:16,130 --> 00:05:16,910 UI. 71 00:05:16,940 --> 00:05:22,400 So for example, with our transparency button, we want to listen for when that gets, uh, clicked 72 00:05:22,400 --> 00:05:25,130 or the mouse gets pressed down on the button. 73 00:05:25,430 --> 00:05:28,670 And that's where we would set currently pressing button equal to true. 74 00:05:29,530 --> 00:05:35,170 And then from that point when we know that we have pressed down on that button, then we can connect 75 00:05:35,170 --> 00:05:41,440 to like, uh, the run service to start updating the position of that slider when the player moves their 76 00:05:41,440 --> 00:05:42,340 mouse around. 77 00:05:42,370 --> 00:05:47,920 However, we also want to listen for when the player releases their mouse off of that button. 78 00:05:47,920 --> 00:05:51,700 And the best way to do that would be to use the input service. 79 00:05:51,700 --> 00:05:56,200 And then we want to listen for the mouse button one input. 80 00:05:56,200 --> 00:06:03,310 Because sometimes, since we're going to be constraining the position of this button to be across our 81 00:06:03,310 --> 00:06:11,200 slider, if the player drags their mouse away and then releases some times, um, it's not going to 82 00:06:11,200 --> 00:06:18,160 be very consistent with firing that, uh, mouse button one up event for the button itself. 83 00:06:18,160 --> 00:06:25,390 So we want to use the user input service to guarantee when the player releases their left mouse button 84 00:06:25,390 --> 00:06:28,330 that we stop moving this slider. 85 00:06:28,600 --> 00:06:33,160 So in the user input service we would listen to the input ended event. 86 00:06:33,910 --> 00:06:36,610 And get that input as well as the game process. 87 00:06:36,610 --> 00:06:37,360 Bouillon. 88 00:06:39,210 --> 00:06:44,940 And then we would actually go ahead and set currently pressing button equal to false when we verify 89 00:06:44,940 --> 00:06:46,410 that the input. 90 00:06:47,330 --> 00:06:49,280 Is equal to mouse button one. 91 00:06:49,280 --> 00:06:53,060 If the user input type is not equal to the enum dot user input. 92 00:06:53,090 --> 00:06:55,100 Type dot mouse button one. 93 00:06:55,100 --> 00:06:56,750 Then we'll just return. 94 00:06:56,750 --> 00:07:02,780 Otherwise we'll know that we are not currently pressing the button once we release the mouse button, 95 00:07:02,780 --> 00:07:03,260 right? 96 00:07:03,970 --> 00:07:11,320 However, when we press down our mouse button, that means we want to connect to the run service. 97 00:07:12,280 --> 00:07:16,990 Dot, we'll get the render step event. 98 00:07:16,990 --> 00:07:23,860 So actually we'll bind to render step and we'll call this slider update. 99 00:07:24,550 --> 00:07:28,810 And the priority is going to be enum dot render priority dot. 100 00:07:29,740 --> 00:07:35,470 Um we'll run it after I don't know we'll do it after the character. 101 00:07:35,470 --> 00:07:38,200 So we'll do character dot value plus one. 102 00:07:39,840 --> 00:07:46,290 And then we'll pass our function, which is actually going to be we're going to use the calculate and 103 00:07:46,290 --> 00:07:50,490 update transparency function for the run service. 104 00:07:51,090 --> 00:07:57,510 So every single frame it's going to calculate the current transparency and update the position of our 105 00:07:57,510 --> 00:08:01,860 slider based on where our mouse is in accordance with this slider. 106 00:08:01,860 --> 00:08:07,710 And then when we release our mouse button then we can go ahead and unbind from the run service. 107 00:08:07,710 --> 00:08:09,450 So we would copy this. 108 00:08:10,480 --> 00:08:12,160 And unbind from render. 109 00:08:12,160 --> 00:08:14,650 Stepped slider update. 110 00:08:15,630 --> 00:08:16,470 Okay, cool. 111 00:08:16,470 --> 00:08:22,980 So what we want to do is we want to go ahead and fill out our calculate and update transparency function. 112 00:08:23,900 --> 00:08:24,890 Inside of here. 113 00:08:24,890 --> 00:08:29,690 What we're going to do is we're first going to get the position of the player's mouse, and we're going 114 00:08:29,690 --> 00:08:35,270 to use the user input service and use the get mouse location function to get the current vector two 115 00:08:35,270 --> 00:08:37,490 of the mouse position on the screen. 116 00:08:37,520 --> 00:08:44,030 Now we want to get the difference between our mouse's current position and the current absolute position 117 00:08:44,030 --> 00:08:47,810 of our slider object here on our screen. 118 00:08:47,810 --> 00:08:50,270 So I'm going to create a variable called difference. 119 00:08:50,270 --> 00:08:52,820 And it's going to be equal to our mouse position. 120 00:08:52,820 --> 00:08:58,460 And we're going to subtract this value by our GUI mainframe. 121 00:08:58,460 --> 00:09:05,390 We're going to get the transparency slider and get its absolute position on the screen in pixels. 122 00:09:06,060 --> 00:09:11,220 So now we have a difference between where our mouse position is at based on the transparency slider. 123 00:09:11,220 --> 00:09:16,680 And from this value, we can go ahead and calculate what the current transparency is. 124 00:09:16,680 --> 00:09:21,300 So when the players mouse moves over then we're going to have a positive value. 125 00:09:21,300 --> 00:09:27,780 And then we can go ahead and calculate that using that difference to see how much that difference matches 126 00:09:27,780 --> 00:09:29,820 the total length of the slider. 127 00:09:29,820 --> 00:09:35,760 So for example if this sliders length is 100 pixels and let's say our mouse is at a halfway point, 128 00:09:35,760 --> 00:09:42,450 which would indicate a difference of 50 pixels, well 50 is half of 100. 129 00:09:42,450 --> 00:09:44,910 So our transparency would be 0.5. 130 00:09:45,450 --> 00:09:48,930 So we can calculate the current transparency. 131 00:09:48,930 --> 00:09:51,930 And we want to make sure we clamp that value between 0 and 1. 132 00:09:51,930 --> 00:09:54,180 So we use the clamp function. 133 00:09:55,160 --> 00:10:00,650 And what we're going to do is we're going to pass our difference here and get its value on the x axis, 134 00:10:00,650 --> 00:10:02,870 because we don't care about the y axis. 135 00:10:02,870 --> 00:10:10,760 Since this is a horizontal slider, and we're going to divide that value by the GUI dot main frame, 136 00:10:10,760 --> 00:10:12,590 get the transparency slider. 137 00:10:12,620 --> 00:10:16,490 And we want to get its absolute size on the x axis. 138 00:10:16,490 --> 00:10:22,760 So now we're getting that uh value which is going to represent the transparency. 139 00:10:22,760 --> 00:10:26,210 And we want to make sure we clamp that value between 0 and 1. 140 00:10:26,270 --> 00:10:31,280 So now we have our new updated transparency that all of the players on our game should be. 141 00:10:32,110 --> 00:10:38,200 And this is where we would like, uh, call our update transparency for all players function and pass 142 00:10:38,200 --> 00:10:41,290 the current transparency at the same time. 143 00:10:41,290 --> 00:10:48,550 We also want to make sure we update the position of that button on our screen to be equal to wherever 144 00:10:48,550 --> 00:10:51,550 the mouse position is on the x axis. 145 00:10:51,550 --> 00:10:57,160 So our transparency button, we want to set the position equal to a new Utum two. 146 00:10:57,930 --> 00:11:03,360 And we're going to basically, uh, set its scale. 147 00:11:03,360 --> 00:11:10,230 So that's going to be equal to whatever the current transparency we have is on the x axis, zero on 148 00:11:10,230 --> 00:11:11,160 the offset. 149 00:11:11,720 --> 00:11:18,380 And then for the Y scale we're just going to get the transparency button dot position dot y dot scale. 150 00:11:18,380 --> 00:11:21,290 So we keep it the same and then zero on the offset. 151 00:11:21,380 --> 00:11:25,970 So now the position of this slider is going to be equal to our current transparency. 152 00:11:25,970 --> 00:11:31,430 So if our mouse moves to the halfway point well our current transparency is going to be 0.5. 153 00:11:31,430 --> 00:11:35,930 And that means the position of this button is going to be set halfway in our slider. 154 00:11:37,540 --> 00:11:42,340 And that means we're going to update all of the transparency for the players in our game. 155 00:11:43,120 --> 00:11:49,030 So inside of this function, what we want to do is we want to loop through every single player inside 156 00:11:49,030 --> 00:11:51,970 of players, get players. 157 00:11:52,210 --> 00:11:57,580 And we want to do is we want to update the transparency for that particular player's character. 158 00:11:57,580 --> 00:12:03,400 So we would pass player character here as well as the current transparency we want to set them to. 159 00:12:03,430 --> 00:12:03,760 Now. 160 00:12:03,760 --> 00:12:07,810 We want to make sure we don't update the transparency for our own character. 161 00:12:08,050 --> 00:12:13,720 So if this player is equal to our local player, then we're just going to continue looping to the next 162 00:12:13,720 --> 00:12:14,260 player. 163 00:12:14,850 --> 00:12:17,580 Now inside of our update transparency for function. 164 00:12:17,580 --> 00:12:22,500 What we're going to do is we're going to first verify that the player has a character, because this 165 00:12:22,500 --> 00:12:23,910 might be nil right here. 166 00:12:24,390 --> 00:12:28,440 So if there is no character then we're just going to return. 167 00:12:28,860 --> 00:12:32,580 Otherwise we're going to loop through every single descendant inside of this character. 168 00:12:32,580 --> 00:12:34,320 Get descendants. 169 00:12:35,680 --> 00:12:39,310 And we want to make sure that this descendant is a base part. 170 00:12:39,310 --> 00:12:42,190 So if this descendant is not a base part. 171 00:12:44,530 --> 00:12:49,570 And we also want to account for any decals in the player's character for like t shirts. 172 00:12:49,570 --> 00:12:53,350 So if this descendant is not a base part and this descendant. 173 00:12:54,330 --> 00:12:59,370 Is not a decal, so not. 174 00:13:00,160 --> 00:13:01,390 D cow. 175 00:13:01,900 --> 00:13:03,460 Looks like I spelt descendants wrong. 176 00:13:03,460 --> 00:13:05,530 So let me fix that descendant. 177 00:13:06,040 --> 00:13:09,220 Then we're just going to continue looping. 178 00:13:09,970 --> 00:13:16,390 Otherwise, what we can go ahead and do is we can go ahead and check to make sure that this descendant 179 00:13:16,390 --> 00:13:21,730 is not the humanoid root part, because the humanoid root part always needs to be transparent. 180 00:13:21,730 --> 00:13:27,310 So if the descendants name is equal to humanoid root part. 181 00:13:29,670 --> 00:13:31,920 Then we can go ahead and just continue. 182 00:13:31,920 --> 00:13:37,050 Or we can also check if you don't want to use the name, you can check if this descendant is equal to 183 00:13:37,050 --> 00:13:41,130 character dot primary part, which would also be the root part. 184 00:13:41,130 --> 00:13:42,870 Then we would continue looping. 185 00:13:42,870 --> 00:13:48,120 Otherwise we're just going to set the transparency of this descendant equal to the transparency passed 186 00:13:48,120 --> 00:13:49,680 to our function. 187 00:13:50,370 --> 00:13:57,240 So now inside of the on character added event, when a new character is added or a new descendant is 188 00:13:57,240 --> 00:14:00,270 added to this character, we want to make sure we update the transparency. 189 00:14:00,270 --> 00:14:06,330 So when a new character is added, we're going to update the transparency for this character with this 190 00:14:06,330 --> 00:14:07,950 new current transparency. 191 00:14:08,220 --> 00:14:14,070 However, when a character is going to be added in our game, there's no guarantee that all of the descendants 192 00:14:14,070 --> 00:14:17,850 in that character are going to be loaded or available to us. 193 00:14:17,850 --> 00:14:23,580 So when we loop through all of the descendants, we might not have all of the descendants in the character. 194 00:14:23,580 --> 00:14:28,830 So we want to listen to this character's descendant added event. 195 00:14:30,430 --> 00:14:33,490 And we'll go ahead and get that descendant. 196 00:14:34,530 --> 00:14:37,380 And basically just copy this stuff right here. 197 00:14:37,380 --> 00:14:40,380 But instead of continue we're going to use the return keywords. 198 00:14:40,650 --> 00:14:45,300 So if this descendant is the primary part or if it's not a base part or decal, we're going to ignore 199 00:14:45,300 --> 00:14:45,720 it. 200 00:14:45,720 --> 00:14:52,590 Otherwise we can go ahead and update the transparency of this descendant equal to, um, our current 201 00:14:52,590 --> 00:14:54,600 transparency that we have. 202 00:14:55,880 --> 00:14:56,480 Okay. 203 00:14:56,480 --> 00:14:56,810 Perfect. 204 00:14:56,810 --> 00:14:58,850 I think this is everything we need set up. 205 00:14:58,850 --> 00:15:05,240 So we listen for when we press down our mouse button and we set this boolean equal to true or false. 206 00:15:05,240 --> 00:15:09,620 And actually let's include this boolean inside calculate and update transparency. 207 00:15:09,620 --> 00:15:13,760 So if we are not currently pressing our button then we're just going to return. 208 00:15:13,940 --> 00:15:20,000 That way we can, you know, prevent any accidental executions of this function if we're not currently 209 00:15:20,000 --> 00:15:22,220 pressing the button just in case. 210 00:15:23,290 --> 00:15:28,960 So when we press down on our text button, we're going to bind to render step to start updating the 211 00:15:28,960 --> 00:15:33,310 slider when the player moves it, and then when they release their mouse button, we know we're not 212 00:15:33,310 --> 00:15:38,290 interacting with that button anymore, so we don't need to update the sliders position. 213 00:15:38,290 --> 00:15:42,880 And as we update the sliders position, we're also going to be updating the transparency for all of 214 00:15:42,880 --> 00:15:44,560 the players in our game. 215 00:15:44,560 --> 00:15:48,550 And we're also going to be listening for when a player's characters are added. 216 00:15:48,550 --> 00:15:55,600 And we're going to update the transparency to match whatever our current transparency is in the game. 217 00:15:55,840 --> 00:15:59,200 So that was a lot of code to write without testing. 218 00:15:59,200 --> 00:16:05,260 So let's actually go ahead and test to see if our slider is actually working in the first place. 219 00:16:05,500 --> 00:16:07,300 So no errors in the console. 220 00:16:07,300 --> 00:16:08,290 That's always great. 221 00:16:08,290 --> 00:16:13,600 And if we click down on our slider, as you can see, it's falling along with the position of our mouse. 222 00:16:13,600 --> 00:16:19,330 And since we're clamping the value of our transparency to be between 0 and 1, it's also clamping the 223 00:16:19,330 --> 00:16:26,230 position of the slider to be between zero and one so it doesn't go beyond the size of our slider. 224 00:16:27,160 --> 00:16:31,510 And then if I release my mouse button, as you can see, I'm no longer interacting with the slider if 225 00:16:31,510 --> 00:16:32,080 I release it. 226 00:16:32,080 --> 00:16:35,500 As you can see, we stop interacting with that slider. 227 00:16:35,500 --> 00:16:41,440 So now we can set up a two player server and check to see if the transparency for other players are 228 00:16:41,440 --> 00:16:42,340 being updated. 229 00:16:43,100 --> 00:16:45,500 Okay, here I am in my two player server. 230 00:16:45,500 --> 00:16:48,170 Let's go ahead and drag this slider. 231 00:16:48,880 --> 00:16:51,940 And as you can see, my player disappears. 232 00:16:51,940 --> 00:16:55,240 And then when I bring it back down, he slowly fades back in. 233 00:16:55,240 --> 00:17:00,850 So now I have complete control over the transparency of other players in my game. 234 00:17:00,850 --> 00:17:05,080 So if I'm playing this obby and I don't like to see other players or interact with other players, then 235 00:17:05,080 --> 00:17:07,270 I can just completely fade them out. 236 00:17:07,270 --> 00:17:13,030 However, we can still collide with them, which means we're going to have to update the collision group 237 00:17:13,030 --> 00:17:17,830 of players in a future lecture to not collide with other players. 238 00:17:18,490 --> 00:17:23,650 But as you can see, each client has independent control over the transparency of other players in the 239 00:17:23,650 --> 00:17:24,310 game. 240 00:17:24,370 --> 00:17:31,900 And even if I keep, let's say, the transparency at this value and I were to die and a new character 241 00:17:31,900 --> 00:17:34,030 of mine were to be added into the game. 242 00:17:34,030 --> 00:17:38,080 I'm still going to keep that transparency that this client has. 243 00:17:38,080 --> 00:17:44,560 And then if I reset this character here, we should keep the player's character still invisible. 244 00:17:44,560 --> 00:17:49,330 So as you can see, I still cannot see him, but I can interact with him because because we haven't 245 00:17:49,330 --> 00:17:51,940 updated the collision group, we'll do that later. 246 00:17:51,940 --> 00:17:57,700 But as you can see so far our slider for player transparency is working great. 247 00:17:59,060 --> 00:18:03,110 That's all I have for you in this lecture, so I'll see you in the next one.